package cn.iocoder.mall.pay.biz.client;

import cn.iocoder.common.framework.util.DateUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO;
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO;
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO;
import com.alibaba.druid.support.spring.stat.SpringStatUtils;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.helpers.DateTimeDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Map;

/***
 *@author yinxucun
 *@date 2019-12-26 14:28 
 */

@Component
public class WxPaySDK extends AbstractPaySDK {

    @Autowired
    WxPayService wxPayService;
    @Autowired
    GeneratorSnowFlakeIDUtils idUtils;
    @Override
    public CommonResult<String> submitTransaction(PayTransactionDO transaction, PayTransactionExtensionDO transactionExtension, Map<String, Object> extra) {

        WxPayUnifiedOrderRequest request=new WxPayUnifiedOrderRequest();
        request.setBody(transaction.getOrderSubject());
        request.setOutTradeNo(transaction.getOrderId());
        request.setTotalFee(transaction.getPrice());
        request.setSpbillCreateIp(transaction.getCreateIp());
        request.setNotifyUrl(transaction.getNotifyUrl());
        request.setTradeType("APP");
        JSONObject returnResult=new JSONObject();
        try {
          WxPayUnifiedOrderResult payResult= wxPayService.unifiedOrder(request);
          if ("SUCCESS".equals(payResult.getResultCode())&&"SUCCESS".equals(payResult.getResultCode())) {
              returnResult.put("prepay_id", payResult.getPrepayId());
              returnResult.put("trade_type", payResult.getTradeType());
              return CommonResult.success(returnResult.toJSONString());
          }
        } catch (WxPayException e) {
            if (e.getCustomErrorMsg()!=null) {
                return CommonResult.error(e.getCustomErrorMsg());
            }
            if (e.getErrCode()!=null){
                returnResult.put("errorCode", e.getErrCode());
                returnResult.put("errorCodeDes", e.getErrCodeDes());
                return CommonResult.error(returnResult.toJSONString());
            }
        }
        return CommonResult.error("提交支付交易失败");
    }

    @Override
    public CommonResult<TransactionSuccessBO> parseTransactionSuccessParams(String params) {
        try {
            final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(params);
            if ("SUCCESS".equals(notifyResult.getResultCode())){
                TransactionSuccessBO transactionSuccessBO=new TransactionSuccessBO();
                transactionSuccessBO.setPaymentTime(DateUtil.parsDateString(notifyResult.getTimeEnd(), "yyyyMMddHHmmss"));
                transactionSuccessBO.setTradeNo(notifyResult.getTransactionId());
                transactionSuccessBO.setTransactionCode(String.valueOf(idUtils.nextId()));
                return CommonResult.success(transactionSuccessBO);
            }
        } catch (WxPayException e) {
            JSONObject returnResult=new JSONObject();
            if (e.getCustomErrorMsg()!=null) {
                return CommonResult.error(e.getCustomErrorMsg());
            }
            if (e.getErrCode()!=null){
                returnResult.put("errorCode", e.getErrCode());
                returnResult.put("errorCodeDes", e.getErrCodeDes());
                return CommonResult.error(returnResult.toJSONString());
            }
        }
        return CommonResult.error("解析失败");
    }

    @Override
    public CommonResult<String> submitRefund(PayRefundDO refund, PayTransactionExtensionDO transactionExtension, Map<String, Object> extra) {
        WxPayRefundRequest wxPayRefundRequest=new WxPayRefundRequest();
        wxPayRefundRequest.setOutRefundNo(refund.getRefundCode());
        wxPayRefundRequest.setOutTradeNo(refund.getOrderId());
        wxPayRefundRequest.setTotalFee(refund.getPrice());
        wxPayRefundRequest.setRefundFee(refund.getPrice());
        wxPayRefundRequest.setNotifyUrl(refund.getNotifyUrl());
        JSONObject returnResult=new JSONObject();
        try {
            WxPayRefundResult refundResult=wxPayService.refund(wxPayRefundRequest);
            if ("SUCCESS".equals(refundResult.getResultCode())&&"SUCCESS".equals(refundResult.getResultCode())) {
                return CommonResult.success(JSONObject.toJSONString(refundResult));
            }
        } catch (WxPayException e) {
            if (e.getCustomErrorMsg()!=null) {
                return CommonResult.error(e.getCustomErrorMsg());
            }
            if (e.getErrCode()!=null){
                returnResult.put("errorCode", e.getErrCode());
                returnResult.put("errorCodeDes", e.getErrCodeDes());
                return CommonResult.error(returnResult.toJSONString());
            }
        }
        return CommonResult.error("提交退款交易失败");
    }

    @Override
    public CommonResult<RefundSuccessBO> parseRefundSuccessParams(String params) {
        try {
            final WxPayRefundNotifyResult notifyResult = wxPayService.parseRefundNotifyResult(params);
            if ("SUCCESS".equals(notifyResult.getResultCode())){
                RefundSuccessBO refundSuccessBO=new RefundSuccessBO();
                refundSuccessBO.setRefundCode(notifyResult.getReqInfo().getOutRefundNo());
                refundSuccessBO.setRefundTime(DateUtil.parsDateString(notifyResult.getReqInfo().getSuccessTime(), "yyyyMMddHHmmss"));
                refundSuccessBO.setSuccess("SUCCESS".equals(notifyResult.getReqInfo().getRefundStatus()));
                refundSuccessBO.setTradeNo(notifyResult.getReqInfo().getTransactionId());
                return CommonResult.success(refundSuccessBO);
            }
        } catch (WxPayException e) {
            JSONObject returnResult=new JSONObject();
            if (e.getCustomErrorMsg()!=null) {
                return CommonResult.error(e.getCustomErrorMsg());
            }
            if (e.getErrCode()!=null){
                returnResult.put("errorCode", e.getErrCode());
                returnResult.put("errorCodeDes", e.getErrCodeDes());
                return CommonResult.error(returnResult.toJSONString());
            }
        }
        return CommonResult.error("解析失败");    }
}
